home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Taifun / Taifun 112 (1989-11-15)(Ossowski, Stefan)(DE)(PD).zip / Taifun 112 (1989-11-15)(Ossowski, Stefan)(DE)(PD).adf / Mischief / Mischief.c < prev    next >
C/C++ Source or Header  |  1989-07-05  |  13KB  |  666 lines

  1. /* Mischief.c ***************************************************************
  2. *
  3. *    Mischief ------    Strange things happening with your Amiga.
  4. *
  5. *            In the spirit of display hacks, you should
  6. *            not continue reading this document unless
  7. *            you really wish to know what this program
  8. *            does. So STOP now.
  9. *
  10. *
  11. *
  12. *
  13. *
  14. *
  15. *
  16. *
  17. *
  18. *
  19. *
  20. *
  21. *
  22. *
  23. *
  24. *
  25. *
  26. *
  27. *
  28. *
  29. *
  30. *
  31. *
  32. *
  33. *
  34. *
  35. *
  36. *
  37. *
  38. *
  39. *
  40. *
  41. *
  42. *
  43. *
  44. *
  45. *
  46. *
  47. *
  48. *
  49. *
  50. *
  51. *            Thank you for reading this document. When I was
  52. *            experimenting with the input.device I discovered
  53. *            some useful methods of controlling the input
  54. *            device as well as some interesting approaches
  55. *            to raw key conversion. Mischief is a playful
  56. *            approach to the 'stern' character of the Amiga
  57. *            resource/library/device system. This program
  58. *            fools the user with events such as:
  59. *
  60. *            o Reversing the use of the mouse buttons.
  61. *
  62. *            o Reversing the direction of mouse moves.
  63. *
  64. *            o Feeding random characters into the
  65. *              input stream instead of the characters
  66. *              the user types.
  67. *
  68. *            o Closing the window under the mouse pointer
  69. *              (only if it has a close gadget).
  70. *
  71. *            o Making the screen sink.
  72. *
  73. *            o Pretending to be the GURU.
  74. *
  75. *            None of these events have a destructive
  76. *            character but you should drop the window
  77. *            you are dragging around as soon as the
  78. *            screen sinks. Moving the screen does not
  79. *            affect the placement of the mouse pointer
  80. *            so it might be possible that Intuition
  81. *            tries to render the outline of the window
  82. *            in a place where there is no screen (CRASH!).
  83. *
  84. *    Author --------    Olaf Barthel, ED Electronic Design Hannover
  85. *            Brabeckstrasse 35
  86. *            D-3000 Hannover 71
  87. *
  88. *            Federal Republic of Germany
  89. *
  90. ****************************************************************************/
  91.  
  92. #include <intuition/intuitionbase.h>
  93. #include <devices/inputevent.h>
  94. #include <graphics/gfxbase.h>
  95. #include <exec/interrupts.h>
  96. #include <devices/input.h>
  97. #include <devices/audio.h>
  98. #include <exec/memory.h>
  99.  
  100.     /* Some external definitions. */
  101.  
  102. extern struct MsgPort    *CreatePort();
  103. extern struct MsgPort    *FindPort();
  104. extern struct Message    *GetMsg();
  105. extern struct IOStdReq    *CreateStdIO();
  106. extern void        *AllocMem();
  107. extern struct Library    *OpenLibrary();
  108. extern struct IOAudio    *DoAnything();
  109. extern struct Layer    *WhichLayer();
  110.  
  111.     /* The libraries we need. */
  112.  
  113. struct IntuitionBase    *IntuitionBase;
  114. struct GfxBase        *GfxBase;
  115. struct Library        *LayersBase;
  116.  
  117.     /* The input.device handling stuff. */
  118.  
  119. struct InputEvent    CopyEvent;
  120. struct MsgPort        *InputDevPort;
  121. struct IOStdReq        *InputRequestBlock;
  122. struct Interrupt    HandlerStuff;
  123. struct MemEntry        Mem[10];
  124.  
  125.     /* The modes we are in. */
  126.  
  127. short            WeAreInMode;
  128. BOOL            HasAnythingChanged = FALSE;
  129. BOOL            LastModeWas = -1;
  130. struct IOAudio        *Laughter;
  131.  
  132.     /* Detach definitions. */
  133.  
  134. long  _stack        = 8000;
  135. long  _priority        = 0;
  136. long  _BackGroundIO    = 0;
  137. char *_procname        = "I'll get you!";
  138.  
  139.     /* Assembler interface to intercept input events before
  140.      * Intuition gets them.
  141.      */
  142.  
  143. extern void Handler();
  144.  
  145. #asm
  146. _Handler:    MOVEM.L    A4,-(A7)    ; Preserve a register
  147.         MOVEM.L    A0/A1,-(A7)    ; Move the data we need
  148.  
  149.         JSR    _geta4#        ; Set up code register (AZTEC)
  150.         JSR    _MyHandler    ; Manipulate the data
  151.  
  152.         ADDQ.L    #8,A7        ; Correct stack
  153.  
  154.         MOVEM.L    (A7)+,A4    ; Restore a register
  155.  
  156.         RTS            ; Continue with the list...
  157. #endasm
  158.  
  159.     /* DoRandom(Code) :
  160.      *
  161.      *    Try to find a random character the handler interface
  162.      *    will feed into the input stream.
  163.      */
  164.  
  165. USHORT
  166. DoRandom(Code)
  167. USHORT Code;
  168. {
  169.     short Length = 0,Start;
  170.  
  171.         /* The following if(...) calls will try
  172.          * to feed only characters into the stream
  173.          * which can be found in the same
  174.          * keyboard row.
  175.          */
  176.  
  177.     if(Code >= 0 && Code <= 13)
  178.     {
  179.         Start    = 0;
  180.         Length    = 14;
  181.     }
  182.  
  183.     if(Code >= 16 && Code <= 27)
  184.     {
  185.         Start    = 16;
  186.         Length    = 12;
  187.     }
  188.  
  189.     if(Code >= 32 && Code <= 43)
  190.     {
  191.         Start    = 32;
  192.         Length    = 12;
  193.     }
  194.  
  195.     if(Code >= 48 && Code <= 59)
  196.     {
  197.         Start    = 48;
  198.         Length    = 12;
  199.     }
  200.  
  201.     if(Length)
  202.         Code = 48 + RangeRand(Length);
  203.  
  204.     return(Code);
  205. }
  206.  
  207.     /* MyHandler(Event,OtherData) :
  208.      *
  209.      *    Just like any interrupt routine this handler receives
  210.      *    pointers to interrupt structures and MemEntry
  211.      *    structures.
  212.      */
  213.  
  214. struct InputEvent *
  215. MyHandler(Event,OtherData)
  216. struct InputEvent *Event;
  217. struct MemEntry *OtherData[];
  218. {
  219.     struct InputEvent *EventPtr, *LastEvent;
  220.     USHORT CodeIs;
  221.  
  222.         /* Tracing the chain of events, try to figure out if
  223.          * there is anything interesting for us.
  224.          *
  225.          * This part of code was borrowed from John Toebes'
  226.          * PopCLI program.
  227.          */
  228.  
  229.     for(EventPtr = Event, LastEvent = NULL ; EventPtr != NULL ; EventPtr = EventPtr -> ie_NextEvent)
  230.     {
  231.         if(EventPtr -> ie_Class == IECLASS_RAWKEY)
  232.         {
  233.                 /* If it's a raw key event and we are in
  234.                  * mode 2 we will feed a random character
  235.                  * into the stream.
  236.                  */
  237.  
  238.             if(WeAreInMode == 2)
  239.             {
  240.                     /* Mask out UP_PREFIX */
  241.  
  242.                 CodeIs = EventPtr -> ie_Code & 0x7F;
  243.  
  244.                     /* Clear original character
  245.                      * code.
  246.                      */
  247.  
  248.                 EventPtr -> ie_Code &= ~CodeIs;
  249.                 EventPtr -> ie_Code |= DoRandom(CodeIs);
  250.  
  251.                     /* Make him laugh. */
  252.  
  253.                 if(LastModeWas != 2)
  254.                 {
  255.                     LastModeWas = 2;
  256.                     HasAnythingChanged = TRUE;
  257.                 }
  258.             }
  259.         }
  260.         else
  261.             LastEvent = EventPtr;
  262.  
  263.         if(EventPtr -> ie_Class == IECLASS_RAWMOUSE)
  264.         {
  265.                 /* If it's a raw mouse event and we
  266.                  * are in mode 3 reverse the mouse
  267.                  * moves.
  268.                  */
  269.  
  270.             if(WeAreInMode == 3)
  271.             {
  272.                 EventPtr -> ie_X = -EventPtr -> ie_X;
  273.                 EventPtr -> ie_Y = -EventPtr -> ie_Y;
  274.  
  275.                 if(LastModeWas != 3)
  276.                 {
  277.                     LastModeWas = 3;
  278.                     HasAnythingChanged = TRUE;
  279.                 }
  280.             }
  281.  
  282.             if(WeAreInMode == 4)
  283.             {
  284.                     /* In mode 4 we will try to
  285.                      * reverse the left and right
  286.                      * mouse button. This works
  287.                      * only with events coming
  288.                      * in from the gameport.device.
  289.                      * If the event comes from the
  290.                      * keyboard.device input.device
  291.                      * will take care of the
  292.                      * transformation on its own and
  293.                      * won't let us know about it.
  294.                      */
  295.  
  296.                 if((EventPtr -> ie_Code & 0x7F) == IECODE_LBUTTON)
  297.                 {
  298.                     EventPtr -> ie_Code &= ~IECODE_LBUTTON;
  299.                     EventPtr -> ie_Code |= IECODE_RBUTTON;
  300.  
  301.                     if(LastModeWas != 4)
  302.                     {
  303.                         LastModeWas = 4;
  304.                         HasAnythingChanged = TRUE;
  305.                     }
  306.  
  307.                     continue;
  308.                 }
  309.  
  310.                 if((EventPtr -> ie_Code & 0x7F) == IECODE_RBUTTON)
  311.                 {
  312.                     EventPtr -> ie_Code &= ~IECODE_RBUTTON;
  313.                     EventPtr -> ie_Code |= IECODE_LBUTTON;
  314.  
  315.                     if(LastModeWas != 4)
  316.                     {
  317.                         LastModeWas = 4;
  318.                         HasAnythingChanged = TRUE;
  319.                     }
  320.  
  321.                     continue;
  322.                 }
  323.             }
  324.         }
  325.     }
  326.  
  327.     return(Event);
  328. }
  329.  
  330.     /* CloseIt(RetCode) :
  331.      *
  332.      *    Close anything there is to close and wave
  333.      *    goodbye.
  334.      */
  335.  
  336. void
  337. CloseIt(RetCode)
  338. long RetCode;
  339. {
  340.     CloseTimerDevice();
  341.  
  342.     if(InputRequestBlock)
  343.     {
  344.         CloseDevice(InputRequestBlock);
  345.         DeleteStdIO(InputRequestBlock);
  346.     }
  347.  
  348.     if(InputDevPort)
  349.         DeletePort(InputDevPort);
  350.  
  351.     if(IntuitionBase)
  352.         CloseLibrary(IntuitionBase);
  353.  
  354.     if(GfxBase)
  355.         CloseLibrary(GfxBase);
  356.  
  357.     if(LayersBase)
  358.         CloseLibrary(LayersBase);
  359.  
  360.     if(Laughter)
  361.         FlushSound(Laughter);
  362.  
  363.     exit(RetCode);
  364. }
  365.  
  366.     /* Save some bytes. */
  367.  
  368. void _cli_parse(){}
  369. void _wb_parse(){}
  370.  
  371. void
  372. main()
  373. {
  374.     struct Screen        *AnyScreen;    /* Make it sink. */
  375.     struct Window        *AnyWindow;    /* Close it. */
  376.     struct MsgPort        *ClosePort;    /* Are we active? */
  377.     struct IntuiMessage    Massage;    /* Fake message. */
  378.     BYTE            *LED = 0xBFE001;/* Power LED. */
  379.     struct MsgPort        *MischiefPort,*ReplyPort;
  380.     struct Message        WakeUp,*Terminate;
  381.     struct Layer_Info    *LayerInfo;    /* Which window? */
  382.     struct Layer        *Layer;
  383.  
  384.     LONG            MouseX,MouseY;    /* Pointer position. */
  385.  
  386.     long            i,j,WaitCount,ActiveCount;    /* Counters. */
  387.  
  388.         /* If we are already around, send the other task
  389.          * a message to close down.
  390.          */
  391.  
  392.     if(MischiefPort = (struct MsgPort *)FindPort("Mischief.port"))
  393.     {
  394.         if(!(ReplyPort = (struct MsgPort *)CreatePort(NULL,0)))
  395.             exit(20);
  396.  
  397.         WakeUp . mn_Node . ln_Type    = NT_MESSAGE;
  398.         WakeUp . mn_Length        = sizeof(struct Message);
  399.         WakeUp . mn_ReplyPort        = ReplyPort;
  400.  
  401.         PutMsg(MischiefPort,&WakeUp);
  402.         WaitPort(ReplyPort);
  403.  
  404.         DeletePort(ReplyPort);
  405.  
  406.         exit(0);
  407.     }
  408.  
  409.         /* Open everything we need. */
  410.  
  411.     if(!(InputDevPort = CreatePort(NULL,0)))
  412.         CloseIt(20);
  413.  
  414.     if(!(InputRequestBlock = CreateStdIO(InputDevPort)))
  415.         CloseIt(20);
  416.  
  417.     if(!OpenTimerDevice())
  418.         CloseIt(20);
  419.  
  420.     if(OpenDevice("input.device",0,InputRequestBlock,0))
  421.         CloseIt(20);
  422.  
  423.     if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0)))
  424.         CloseIt(20);
  425.  
  426.     if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0)))
  427.         CloseIt(20);
  428.  
  429.     if(!(LayersBase = (struct Library *)OpenLibrary("layers.library",0)))
  430.         CloseIt(20);
  431.  
  432.     if(!(Laughter = (struct IOAudio *)DoAnything()))
  433.         CloseIt(20);
  434.  
  435.     if(!(MischiefPort = (struct MsgPort *)CreatePort("Mischief.port",0)))
  436.         CloseIt(20);
  437.  
  438.         /* Tell input.device to insert our handler code at the
  439.          * top of the chain.
  440.          */
  441.  
  442.     HandlerStuff . is_Data        = (APTR)&Mem[0];
  443.     HandlerStuff . is_Code        = Handler;
  444.     HandlerStuff . is_Node . ln_Pri    = 51;
  445.  
  446.     InputRequestBlock -> io_Command    = IND_ADDHANDLER;
  447.     InputRequestBlock -> io_Data    = (APTR)&HandlerStuff;
  448.  
  449.     DoIO(InputRequestBlock);
  450.  
  451.         /* Clear the copy of the input event. */
  452.  
  453.     CopyEvent . ie_TimeStamp . tv_secs    = 0;
  454.     CopyEvent . ie_TimeStamp . tv_micro    = 0;
  455.     CopyEvent . ie_Class            = 0;
  456.  
  457.         /* Initialize counters and prepare the sound. */
  458.  
  459.     WaitCount = 10 * (RangeRand(10) + 1);
  460.     WeAreInMode = RangeRand(6);
  461.  
  462.     BeginIO(Laughter);
  463.     WaitIO(Laughter);
  464.  
  465.     Laughter -> ioa_Volume = 64;
  466.  
  467.     FOREVER
  468.     {
  469.             /* Wait some time... */
  470.  
  471.         WaitTime(0,100000);
  472.  
  473.             /* Has anything change? Then laugh a bit. */
  474.  
  475.         if(HasAnythingChanged)
  476.         {
  477.             HearSound(Laughter);
  478.             HasAnythingChanged = FALSE;
  479.         }
  480.  
  481.             /* Any mail for us? */
  482.  
  483.         if(Terminate = (struct Message *)GetMsg(MischiefPort))
  484.         {
  485.             ReplyMsg(Terminate);
  486.             DeletePort(MischiefPort);
  487.  
  488.                 /* Give him a BIG smile... */
  489.  
  490.             Laughter -> ioa_Period *= 2;
  491.             HearSound(Laughter);
  492.  
  493.             break;
  494.         }
  495.  
  496.             /* Having done our mischievious work, we wait
  497.              * a moment.
  498.              */
  499.  
  500.         if(WaitCount > 0)
  501.         {
  502.             WaitCount--;
  503.             ActiveCount = -1;
  504.  
  505.             continue;
  506.         }
  507.  
  508.             /* If we are active, decrement the counter. */
  509.  
  510.         if(ActiveCount > 0)
  511.         {
  512.             ActiveCount--;
  513.             WaitCount = -1;
  514.         }
  515.         else
  516.         {
  517.                 /* Finished? Chose a new period and
  518.                  * a new mode.
  519.                  */
  520.  
  521.             if(!WaitCount)
  522.             {
  523.                 WeAreInMode = RangeRand(6);
  524.                 ActiveCount = 10 * (RangeRand(10) + 1);
  525.             }
  526.             else
  527.             {
  528.                 WaitCount = 10 * (RangeRand(10) + 1);
  529.                 ActiveCount = -1;
  530.  
  531.                 continue;
  532.             }
  533.         }
  534.  
  535.             /* If we are in mode 0 let the active screen
  536.              * sink.
  537.              */
  538.  
  539.         if(WeAreInMode == 0)
  540.         {
  541.             if(LastModeWas != 0)
  542.             {
  543.                 LastModeWas = 0;
  544.                 HearSound(Laughter);
  545.             }
  546.  
  547.             AnyScreen = IntuitionBase -> ActiveScreen;
  548.             MoveScreen(AnyScreen,0,1);
  549.         }
  550.  
  551.             /* If we are in mode 1 we will try to
  552.              * close the window the pointer is
  553.              * "hovering" over. If this window
  554.              * doesn't have any close gadget we
  555.              * won't do anything.
  556.              */
  557.  
  558.         if(WeAreInMode == 1)
  559.         {
  560.             Forbid();
  561.  
  562.                 /* Try to find the window under
  563.                  * the mouse pointer.
  564.                  */
  565.  
  566.             LayerInfo = &IntuitionBase -> ActiveScreen -> LayerInfo;
  567.  
  568.             LockLayerInfo(LayerInfo);
  569.  
  570.             MouseX = IntuitionBase -> ActiveScreen -> MouseX;
  571.             MouseY = IntuitionBase -> ActiveScreen -> MouseY;
  572.  
  573.                 /* Any layer under the pointer? */
  574.  
  575.             if(!(Layer = (struct Layer *)WhichLayer(LayerInfo,MouseX,MouseY)))
  576.             {
  577.                 Permit();
  578.                 continue;
  579.             }
  580.  
  581.             AnyWindow = (struct Window *)Layer -> Window;
  582.  
  583.             UnlockLayerInfo(LayerInfo);
  584.  
  585.             Permit();
  586.  
  587.                 /* If it has a close gadget pretend
  588.                  * we are the user who has hit
  589.                  * it.
  590.                  */
  591.  
  592.             if(AnyWindow -> Flags & WINDOWCLOSE)
  593.             {
  594.                 if(ClosePort = CreatePort(NULL,0))
  595.                 {
  596.                     setmem(&Massage,sizeof(struct IntuiMessage),0);
  597.  
  598.                         /* Let's pretend we are Intuition
  599.                          * and are sending a CLOSEWINDOW
  600.                          * message.
  601.                          */
  602.  
  603.                     Massage . ExecMessage . mn_Node . ln_Type    = NT_MESSAGE;
  604.                     Massage . ExecMessage . mn_Length        = sizeof(struct IntuiMessage);
  605.                     Massage . ExecMessage . mn_ReplyPort        = ClosePort;
  606.  
  607.                     Massage . Class                    = CLOSEWINDOW;
  608.                     Massage . IDCMPWindow                = AnyWindow;
  609.  
  610.                         /* Put it where it belongs,
  611.                          * and hope for a reply.
  612.                          */
  613.  
  614.                     PutMsg(AnyWindow -> UserPort,&Massage);
  615.                     WaitPort(ClosePort);
  616.  
  617.                     DeletePort(ClosePort);
  618.  
  619.                     if(LastModeWas != 1)
  620.                     {
  621.                         LastModeWas = 1;
  622.                         HasAnythingChanged = TRUE;
  623.                     }
  624.                 }
  625.             }
  626.         }
  627.  
  628.             /* If we are in mode 5 we freeze the machine
  629.              * and try to make the user believe a guru
  630.              * is soon to come.
  631.              */
  632.  
  633.         if(WeAreInMode == 5)
  634.         {
  635.             Forbid();
  636.  
  637.             for(i = 0 ; i < 4 ; i++)
  638.             {
  639.                 *LED |= 2;
  640.                 for(j = 0 ; j < 90000 ; j++);
  641.  
  642.                 *LED &= 253;
  643.                 for(j = 0 ; j < 90000 ; j++);
  644.             }
  645.  
  646.             Permit();
  647.  
  648.             HasAnythingChanged = TRUE;
  649.  
  650.             WaitCount = 10 * (RangeRand(10) + 1);
  651.             ActiveCount = -1;
  652.  
  653.             continue;
  654.         }
  655.     }
  656.  
  657.         /* Remove the handler. */
  658.  
  659.     InputRequestBlock -> io_Command    = IND_REMHANDLER;
  660.     InputRequestBlock -> io_Data    = (APTR)&HandlerStuff;
  661.  
  662.     DoIO(InputRequestBlock);
  663.  
  664.     CloseIt(0);
  665. }
  666.